﻿using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using SY.WebApiTool.Interface;
using SY.WebApiTool.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;

namespace SY.WebApiTool.Tool
{
    public class MaterialTool : IWebApiTool
    {
        private ValidateTool validateTool;
        private HttpClient httpClient;
        public string CloudServerAdress { get; set; } = "";
        public List<Material> Materials { get; set; }
        private string formId;
        private IJsonFormatTool formatTool = new MaterialJsonFormatTool();

        private string cloudUrl { get { return CloudServerAdress +
                    (
                    CloudServerAdress.ToLower().Contains("k3cloud")?"":
                        CloudServerAdress.Length > 0 ?
                            (CloudServerAdress.Substring(CloudServerAdress.Length - 2, 1).Equals("/") ? "k3cloud" : "/k3cloud") : ""
                    ); } }
        private bool validated = false;

        public MaterialTool(string accid, string cloudServerAdress,string userName = "administrator", string password= "888888", int lcid = 2052)
        {
            validateTool = new ValidateTool() { AccId = accid, UserName = userName, Password = password, Lcid = lcid };
            httpClient = new HttpClient();
            CloudServerAdress = cloudServerAdress;
            formId = "BD_MATERIAL";
        }

        /// <summary>
        /// 登录校验
        /// </summary>
        void IWebApiTool.Validate()
        {
            if (String.IsNullOrEmpty(cloudUrl))
                throw new Exception("未输入K3Cloud登录地址");

            httpClient.Url = cloudUrl + "/Kingdee.BOS.WebApi.ServicesStub.AuthService.ValidateUser.common.kdsvc";
            List<object> parameters = new List<object> { validateTool.AccId, validateTool.UserName, validateTool.Password, validateTool.Lcid };
            httpClient.Content = JsonConvert.SerializeObject(parameters);
            var iResult = JObject.Parse(httpClient.AsyncRequest())["LoginResultType"].Value<int>();
            validated = iResult == 1;
        }

        
        IJsonResult IWebApiTool.Save()
        {
            ToolValidate();

            string json = formatTool.BatchSaveJson(Materials);            

            return PostRequest(httpClient, json, OperationType.Save);
            
        }

        IJsonResult IWebApiTool.Summit()
        {
            ToolValidate();

            string json = formatTool.BatchSummitJson(Materials.Select(p => p.FNumber)).Replace(Environment.NewLine, "").Replace(" ", "");

            return PostRequest(httpClient, json, OperationType.Summit);
        }

        IJsonResult IWebApiTool.Audit()
        {
            ToolValidate();

            string json = formatTool.BatchAuditJson(Materials.Select(p => p.FNumber)).Replace(Environment.NewLine, "").Replace(" ", "");

            return PostRequest(httpClient, json, OperationType.Audit);
        }

        IJsonResult Update()
        {
            ToolValidate();
            List<Material> update = Materials.Where(o => o.FNumber != "")?.ToList();
            string jsonUpdate = update.Count == 0 ? null : formatTool.BatchUpdateJson(update.Select(p => p.JsonData())).Replace(Environment.NewLine, "").Replace(" ", "");
            return PostRequest(httpClient, jsonUpdate, OperationType.Save);
        }


        private IEnumerable<Material> InitialMaterials()
        {
            return new List<Material> { new Material("TestApi", "100", "100") };
        }

        /// <summary>
        /// 校验是否进行过登录操作及物料信息是否为空
        /// </summary>
        private void ToolValidate()
        {
            if (!validated)
            {
                throw new Exception("未进行Validate（登录校验）操作");
            }
            if (Materials == null)
                throw new Exception("未输入物料信息(Materials属性未赋值)");
        }

        private MaterialJsonResult PostRequest(HttpClient client, String json, OperationType operationType)
        {
            List<Object> parameters = new List<object> { formId };
            parameters.Add(json);
            httpClient.Content = JsonConvert.SerializeObject(parameters);

            switch (operationType)
            {
                case OperationType.Save:
                    httpClient.Url = cloudUrl + "/Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.BatchSave.common.kdsvc";
                    break;
                case OperationType.Summit:
                    httpClient.Url = cloudUrl + "/Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.Submit.common.kdsvc";
                    break;
                case OperationType.Audit:
                    httpClient.Url = cloudUrl + "/Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.Audit.common.kdsvc";
                    break;
                default:
                    break;
            }

            try
            {
                return JsonConvert.DeserializeObject<MaterialJsonResult>(httpClient.AsyncRequest());
            }
            catch (Exception)
            {
                String operate = operationType.ToString();
                throw new Exception($"({operate})时调用httpClient.AsyncRequest()时出错");
            }
        }


        private MaterialJsonResult PostRequest(HttpClient client, List<string> json, OperationType operationType = OperationType.Save)
        {
            List<Object> parameters = new List<object> { formId };
            parameters.AddRange(json);
            httpClient.Content = JsonConvert.SerializeObject(parameters);

            switch (operationType)
            {
                case OperationType.Save:
                    httpClient.Url = cloudUrl + "/Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.BatchSave.common.kdsvc";
                    break;
                default:
                    throw new Exception("此PostRequest(HttpClient client,List<string> json,OperationType operationType=OperationType.Save)方法只用于保存");

            }

            try
            {
                return JsonConvert.DeserializeObject<MaterialJsonResult>(httpClient.AsyncRequest());
            }
            catch (Exception)
            {
                String operate = operationType.ToString();
                throw new Exception($"({operate})时调用httpClient.AsyncRequest()时出错");
            }
        }



        public string ValidateReturn()
        {
            (this as IWebApiTool).Validate();
            return validated.ToString();
        }

        public static IEnumerable<ResultInfoModel> ResutlInfoReturn(MaterialJsonResult jsonResult,OperationType operation)
        {
            int count = 0;
            if (jsonResult.Result.ResponseStatus.SuccessEntitys.Count() == 0)
            {
                count = jsonResult.Result.ResponseStatus.Errors?.OrderBy(p => p.DIndex).Last().DIndex??0;
            }
            else if (jsonResult.Result.ResponseStatus.Errors.Count() == 0)
            {
                count = jsonResult.Result.ResponseStatus.SuccessEntitys?.OrderBy(p => p.DIndex)?.Last()?.DIndex ?? 0;
            }
            else
            {
                count=Math.Max(jsonResult.Result.ResponseStatus.SuccessEntitys?.OrderBy(p => p.DIndex)?.Last()?.DIndex ?? 0, jsonResult.Result.ResponseStatus.Errors?.OrderBy(p => p.DIndex)?.Last()?.DIndex ?? 0);
            }

            
            List<ResultInfoModel> returns = new List<ResultInfoModel>();
            for (int i = 0; i < count+1; i++)
            {
                returns.Add(new ResultInfoModel());
            }
                   

            foreach (var item in jsonResult.Result.ResponseStatus.Errors)
            {
                var b = returns[item.DIndex];
                b.Index = item.DIndex;
                b.Succeed = false;
                b.ErrorInfo += $"错误字段{item.FieldName},错误信息{item.Message};";

            }

            foreach (var item in jsonResult.Result.ResponseStatus.SuccessEntitys)
            {
                var b = returns[item.DIndex];
                b.Index = item.DIndex;
                b.Succeed = true;
                b.Id = item.Id;
                b.Number = item.Number;
                if(operation==OperationType.Save)
                    b.Name = jsonResult.Result.NeedReturnData.Where(p => p.FMATERIALID == item.Id).Select(q => q.FName).FirstOrDefault();
            }
            return returns;
        }
    }

    /// <summary>
    /// 用于将服务器返回的JSON数据转为实体的实体类
    /// </summary>
    public class ResultInfoModel
    {
        public int Index { get; set; }
        public long Id { get; set; }
        public string Name { get; set; }
        public string Number { get; set; }
        public bool Succeed { get; set; }
        public string ErrorInfo { get; set; }   

    }

    public enum OperationType
    {
        Save,
        Summit,
        Audit
    }
    
}
